#pragma once
#include<iostream>
using namespace std;
#include<stdarg.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#define SIZE 1024

#define Info 0
#define Debug 1
#define Waring 2
#define Error 3
#define Fatal 4

#define Screen 1
#define Onefile 2
#define Classfile 3

#define LogFile "log.txt"

class Log
{
public:
    Log()
    {
        printStyle = Screen;    //默认打印到屏幕上
        path = "./log/";        //默认的路径是./log/
    }

    void Enable(int method)
    {
        printStyle = method;
    }

    void printOneFile(const string& logname, const string& logtxt)
    {
        string _logname = path + logname;   //打印到的文件路径
        int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0660);
        if (fd < 0) return;
        write(fd, logtxt.c_str(), logtxt.size()); //文件描述符，文件源， 文件大小
        close(fd);
    }

    void printClassFile(int level, const string& logtxt)
    {
        //创建文件夹的文件名
        string filename = LogFile;
        filename += ".";
        filename += LevelToString(level);

        printOneFile(filename, logtxt);  //然后去这个文件里打印数据
    }


    void printLog(int level, const string logtxt)
    {
        switch(printStyle)
        {
            case Screen:
                cout << logtxt << endl;
                break;
            case Onefile:
                printOneFile(LogFile, logtxt); //向文件里面打, 这个文件名定义的是LogFile            
                break;
            case Classfile:
                printClassFile(level, logtxt);
                break;
            default:
                break;
        }
    }


    void operator()(int level, const char* format, ...)
    {
        //获取时间
        time_t t = time(nullptr); 
        struct tm* ctime = localtime(&t); 
        char leftbuffer[SIZE];   

        snprintf(leftbuffer, sizeof(leftbuffer), 
        "[%s][%d-%d-%d-%d-%d-%d]", LevelToString(level).c_str(), ctime->tm_year
        ,ctime->tm_mon, ctime->tm_mday, ctime->tm_hour, ctime->tm_min
        , ctime->tm_sec);    //向缓冲区中打印数据

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];

        vsnprintf(rightbuffer, sizeof(rightbuffer), format,s); //
        va_end(s);

        char logtxt[SIZE * 2]; //文本缓冲区， 用来将两个文本文件合起来;
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer
        , rightbuffer);

        //将要打印的数据放到缓冲区里面后就可以打印数据了
        printLog(level, logtxt);
    }

    string LevelToString(int level)
    {
        switch(level)
        {
            case Info:
                return "Info";
            case Debug:
                return "Debug";
            case Waring:
                return "Waring";
            case Error:
                return "Error";
            default:
                return "None";
        }
    }


public:
    int printStyle; //打印风格
    string path; //打印到那个路径下面
};